Skip to content

Add hub for Dev Archipelago#2545

Open
felixwalberg wants to merge 4 commits into
mainfrom
dev-archipelago-hub
Open

Add hub for Dev Archipelago#2545
felixwalberg wants to merge 4 commits into
mainfrom
dev-archipelago-hub

Conversation

@felixwalberg

@felixwalberg felixwalberg commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

This PR introduces a scene dev_archipelago.tscn, which will eventually be connected to Fray's End. The scene consists of a few islands, some of which are themed to correspond with mechanics in the game. Each island will have its own elder and set of quests leading to test scenes, gyms, and other playable documentation. The bridge behind the initial spawn point teleports the player back to frays_end.tscn.

Resolves #2531

@github-actions

Copy link
Copy Markdown

Play this branch at https://play.threadbare.game/branches/endlessm/dev-archipelago-hub/.

(This launches the game from the start, not directly at the change(s) in this pull request.)

@felixwalberg

Copy link
Copy Markdown
Contributor Author

Still need:

@felixwalberg
felixwalberg marked this pull request as ready for review July 16, 2026 18:29
@felixwalberg
felixwalberg requested a review from a team as a code owner July 16, 2026 18:29
@felixwalberg

Copy link
Copy Markdown
Contributor Author

This doesn't address all the needs of the Dev Archipelago hub, but I wanted to open it up to review before it gets too big!

Comment on lines +30 to +34
## Optional dialogue passed to `TalkBehavior`. Used when
## instantiating an elder in a scene that doesn't use the standard
## eternal loom dialogue flow.
@export var dialogue: Resource

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 3 elders in Fray's End actually already have different dialogues: they are each an instance of a different scene, so we can just set the TalkBehavior node's dialogue directly in each one.

Though if there are many elders in the archipelago I can see why you want to avoid continuing that trend. I think it's fine to do this. I wish Godot had a built-in way to export specific properties of child nodes from the root of the owning scene!

# SPDX-FileCopyrightText: The Threadbare Authors
# SPDX-License-Identifier: MPL-2.0
~ start
# TODO: Name is up for debate

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I love it. I laughed out loud when I got the joke.

Comment on lines +4 to +5
@onready var repel_timer: Timer = %RepelTimer
@onready var repel_timer_2: Timer = $Sheep2/PlayerRepel2/RepelTimer2

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest either consistently using % unique names, or using @exports. But...


## Called when the node enters the scene tree for the first time.
func _ready() -> void:
if repel_timer_2.is_node_ready():

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...this is guaranteed by the scene structure. A node becomes ready after all its children are ready. But...

Comment on lines +11 to +12
await get_tree().create_timer(.5).timeout
repel_timer.start()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the other two timers are nodes in the scene, I would personally structure this with a third timer, with autostart set to True, timeout set to 0.5, oneshot set to true, and connect its timeout to start on RepelTimer. I think that makes the whole setup more consistent: it's all done in the scene tree.

% Basics Elder: The people of Threadbare are counting on you. Your understanding of our world is necessary for its survival!
else:
% Basics Elder: Excellent choice, your training will surely help with your world-saving efforts.
% Basics Elder: Ah, those! Capable of such inginuity. To do what? I can't quite remember...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
% Basics Elder: Ah, those! Capable of such inginuity. To do what? I can't quite remember...
% Basics Elder: Ah, those! Capable of such ingenuity. To do what? I can't quite remember...

Comment on lines +29 to +32
if hook_control_1.state == 1:
hook_control_1.state = 0
if hook_control_2.state == 1:
hook_control_2.state = 0

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you not use HookControl.State.AIMING rather than 1 here?

Comment on lines +18 to +23
player_hook.remove_from_group("hook_listener")
player_hook_2.remove_from_group("hook_listener")
hook_control_1 = player_hook.find_child("HookControl")
hook_control_2 = player_hook_2.find_child("HookControl")
hook_control_1.state = 0
hook_control_2.state = 0

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting. That component really wasn't designed for non-interactive use! I think this is fine as a workaround but rather than the boilerplate "called when..." comments, I think it would be worth documenting here why these lines are needed (as below for the state).


first_sheep.hooked(hookable_box.find_child("HookableArea"), true)

await get_tree().create_timer(max(randf() * MAX_DELAY, MIN_DELAY)).timeout

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
await get_tree().create_timer(max(randf() * MAX_DELAY, MIN_DELAY)).timeout
await get_tree().create_timer(randf_range(MIN_DELAY, MAX_DELAY)).timeout

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love how this scene is taking shape.

Some minor nitpicking about foam:

Image

Red circle: as documented on https://github.com/endlessm/threadbare/wiki/TileMapLayers-and-TileSets#foam the fake perspective means that the top edge of a patch of grass raised "one level" above the water should not have foam.

Blue circle: if you look closely you can see the foam through the cliff, which is because there is no cliff underneath that patch of grass:

Image

@wjt

wjt commented Jul 17, 2026

Copy link
Copy Markdown
Member

Feel free to fix the suggestions either in this PR before merging, or later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dev Archipelago: Design the Hub scene

2 participants